//
//  DBUtility.m
//  ChatForHot
//
//  Created by FLY on 2018/10/17.
//  Copyright © 2018年 FLY. All rights reserved.
//

#import "DBUtility.h"

@implementation DBUtility

static DBUtility *_dbshare;

@synthesize fmdbQueue = fmdbQueue;

+ (id)sharedbUtility {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _dbshare = [[DBUtility alloc] init];
    });
    return _dbshare;
}

- (NSString*)dbPath {
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* documentsDir = [paths objectAtIndex:0];
    return [documentsDir stringByAppendingPathComponent:DB_FILE_NAME];
}

- (void)dealloc {
    [self close];
}

- (void)open {
    fmdbQueue = [[FMDatabaseQueue alloc] initWithPath:[self dbPath]];
}

- (void)close {
    [fmdbQueue close];
    fmdbQueue = nil;
}

-(BOOL)executeUpdate:(NSString*)sql{
    __block BOOL result = YES;
    DBUtility *dbutility = (DBUtility *)[DBUtility sharedbUtility];
    [dbutility open];
    
    [dbutility.fmdbQueue inDeferredTransaction:^(FMDatabase *db, BOOL *rollback) {
        
        if ( ![db executeUpdate:sql] ) {
//            DB_ERROR_LOG(@"DBUtility33")
            *rollback = YES;
            result = NO;
        }
    }];
    [dbutility close];
    return result;
    
}

- (void)applicationLauching {
    [self open];
//    [self selectVersion];
    [self updateVersion];
    [self close];
}
- (void)updateVersion{
    
    [fmdbQueue inDeferredTransaction:^(FMDatabase *db, BOOL *rollback) {
        NSMutableArray* sqlArr = [NSMutableArray arrayWithCapacity:2];
        [sqlArr addObject:@"CREATE TABLE IMInfo(accountid text(10),IMUser text(10) NOT NULL,nickName text(20),headPic text(20),vip text(5),signal text,PRIMARY KEY(accountid))"];
        [sqlArr addObject:@"CREATE TABLE guestlist(accountid text(10) NOT NULL,myid text(10) NOT NULL,IMUser text(10),nickName text(20),headPic text(20),vip text(5),date text(10),issee int default 0,other text,PRIMARY KEY(accountid,myid))"];
        for ( NSString* sql in sqlArr ) {
            if ( ![db executeUpdate:sql] ) {
//                DB_ERROR_LOG(NSStringFromClass([self class]))
                *rollback = YES;
                return;
            }
        }

    }];
}
- (void)applicationTerminating {
    // backup
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSString* dbPath = [self dbPath];
    if ( ![fileManager fileExistsAtPath:dbPath] ) {
        return;
    }
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString* documentsDir = [paths objectAtIndex:0];
    NSError* error;
    // backup
    NSString* backupDir = [documentsDir stringByAppendingPathComponent:@"backup"];
    if ( ![fileManager createDirectoryAtPath:backupDir withIntermediateDirectories:YES attributes:nil error:&error] ) {
        NSLog( @"failed to create backup dir : %@", [error localizedDescription] );
        return;
    }
    // DB复制
    NSDateFormatter* formatter = [[NSDateFormatter alloc] init];
    [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US"]];
    [formatter setDateFormat:@"yyyyMMddHHmmss"];
    NSString* date = [formatter stringFromDate:[NSDate date]];
    NSString* backupPath = [NSString stringWithFormat:@"%@/backup%@.sqlite3", backupDir, date];
    if ( ![fileManager copyItemAtPath:dbPath toPath:backupPath error:&error] ) {
        NSLog( @"fail database : %@", [error localizedDescription] );
        return;
    }
    // backupNum
    const int backupNum = 2;
    NSArray* files = [fileManager contentsOfDirectoryAtPath:backupDir error:&error];
    files = [files sortedArrayUsingSelector:@selector(compare:)];// 昇順
    for ( NSInteger i = [files count]-1-backupNum; i >= 0; i-- ) {
        NSString* path = [backupDir stringByAppendingPathComponent:[files objectAtIndex:i]];
        [fileManager removeItemAtPath:path error:&error];
    }
    // DB clear
    [self vacuum];
    
    if (![self check]) {
        [self dbCancel :backupPath];
    }
}

- (void)vacuum {
    NSOperationQueue* opeQ = [NSOperationQueue mainQueue];
    [opeQ addOperationWithBlock:^{
        [self open];
        [self->fmdbQueue inDatabase:^(FMDatabase *db) {
            NSString* sql = @"VACUUM";
            [db executeUpdate:sql];
        }];
        [self close];
    }];
}

- (BOOL)check {
    __block BOOL res = NO;
    DBUtility *dbutility = (DBUtility *)[DBUtility sharedbUtility];
    [dbutility open];
    [dbutility.fmdbQueue inDatabase:^(FMDatabase *db) {
        @try {
            NSString *sql =@"PRAGMA integrity_check";
            FMResultSet *results = [db executeQuery:sql];
            while( [results next] )
            {
                if ([[results stringForColumn:@"integrity_check"] isEqualToString:@"OK"]) {
                    res= YES;
                }
            }
        }@catch (NSException *exception) {
            
            NSLog(@"Exception:check");
        }
    }];
    [dbutility close];
    return res;
}

-(void)dbCancel:(NSString *)path{
    NSFileManager* fileManager = [NSFileManager defaultManager];
    NSString* dbPath = [self dbPath];
    NSError* error;
    [fileManager removeItemAtPath:dbPath error:&error];
    if ( ![fileManager copyItemAtPath:path toPath:dbPath error:&error] ) {
        NSLog( @"dbCanceled : %@", [error localizedDescription] );
        return;
    }
}


@end
